<!--
 * @Description: 视点保存组件
 * @Author:       dingyi
 * @Date: 2021-11-03 16:51:52
 * @LastEditors:  dingyi
 * @LastEditTime: 2021-11-03 18:44:56
-->
<template>
  <div class="viewPosition">
    <div class="header">是否保存当前视点配置?</div>
    <div class="form">
      <button
        class="cancel"
        @click="cancel">取消</button>
      <button
        class="confirm"
        @click="confirm">确定</button>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, defineExpose, defineEmits } from 'vue'
import dmap from '../../assets/dmap/dmap-es'
import { getLayerGroupDetails } from '@/api/layer/layergroup'
import MapStyle from '../../config/styleConfig'

const curruntGroupId = ref()
const serverRangeList = ref([])

const emit = defineEmits(['close', 'confirm'])

/**
 * 初始化视点
 */
const init = (id) => {
  console.log(id)
  if (id) {
    curruntGroupId.value = id
    addServerList()
  }
}

/**
 * 关闭窗口
 */
const cancel = () => {
  removeLayerGroup()
  serverRangeList.value = []
  curruntGroupId.value = undefined
  emit('close')
}

/**
 * 保存视点
 */
const confirm = () => {
  removeLayerGroup()
  serverRangeList.value = []
  curruntGroupId.value = undefined
  emit('confirm', window.viewer.dCamera.getCameraInfo())
}

/**
 * 根据图层组标识添加服务集合
 * @param {Number} id 图层组标识
 */
const addServerList = () => {
  getLayerGroupDetails(curruntGroupId.value).then((value) => {
    const layerGroupDataRes = dataProcessing(value.data)
    addLayerGroup(layerGroupDataRes)
    locationLayerGroup(value.data)
  })
}

/**
 * 图层组定位
 * @param {Object} data
 */
const locationLayerGroup = (data) => {
  const { lng, lat, level, heading, pitch } = data
  if (lng && lat && level && heading && pitch) {
    window.viewer.dCamera.flyToPoint(
      Number(lng),
      Number(lat),
      Number(level),
      2,
      Number(heading),
      Number(pitch)
    )
  } else {
    const lngs = []
    const lats = []
    serverRangeList.value.forEach((value) => {
      const range = value.split(',')
      if (value !== '' && range.length === 4) {
        lngs.push(Number(range[0]))
        lngs.push(Number(range[2]))
        lats.push(Number(range[1]))
        lats.push(Number(range[3]))
      }
    })
    if (lngs.length >= 2 && lats.length >= 2) {
      const maxLng = dmap.ArrayUtil.max(lngs)
      const minLng = dmap.ArrayUtil.min(lngs)
      const maxLat = dmap.ArrayUtil.max(lats)
      const minLat = dmap.ArrayUtil.min(lats)
      const coordinates = dmap.CoordinateUtil.lngLatsToCartesianArray([
        [minLng, minLat],
        [maxLng, maxLat]
      ])
      window.viewer.dCamera.flyToRectangle(coordinates)
    }
  }
}

/**
 * 添加图层组
 * @param {Object} data 接口请求图层组详情数据处理后的数据
 * 1、创建对应图层组
 * 2、根据图层组存在的数据来创建不同图层
 */
function addLayerGroup (data) {
  const layerGroup = new dmap.LayerGroup({ id: curruntGroupId.value })
  for (const key in data) {
    if (Object.hasOwnProperty.call(data, key)) {
      // 循环数据，创建图层
      addLayer(key, data[key], layerGroup)
    }
  }
  window.viewer.layerCollection.addLayer(layerGroup)
}
/**
 * 添加图层
 * @param {String} key 添加图层的类型
 * @param {String} data 添加图层对应的服务数据，处理完成后的成果数据
 * @param {Object} layerGroup 对应添加的图层组对象
 */
function addLayer (key, data, layerGroup) {
  switch (key) {
    case dmap.LayerType.MVT:
      data.geoLayerConfigs.forEach((value) => {
        const layer = new dmap.MvtLayer(value)
        layerGroup.addLayer(layer)
      })
      break
    case dmap.LayerType.BUILDING:
      data.geoLayerConfigs.forEach((value) => {
        const layer = new dmap.BuildingLayer(value)
        layerGroup.addLayer(layer)
      })
      break
    case dmap.LayerType.MODEL:
      data.geoLayerConfigs.forEach((value) => {
        const layer = new dmap.ModelLayer(value)
        layerGroup.addLayer(layer)
      })
      break
    case dmap.LayerType.IMAGE:
      data.geoLayerConfigs.forEach((value) => {
        const layer = new dmap.ImageLayer(value)
        layerGroup.addLayer(layer)
      })
      break
    case dmap.LayerType.TERRAIN:
      data.geoLayerConfigs.forEach((value) => {
        const layer = new dmap.TerrainLayer(value)
        layerGroup.addLayer(layer)
      })
      break
    case dmap.LayerType.TERMINAL:
      {
        const layer = new dmap.TerminalLayer() // 终端图层
        layerGroup.addLayer(layer)
      }
      break
    case dmap.LayerType.GRID:
      {
        const layer = new dmap.GridLayer() // 网格图层
        layerGroup.addLayer(layer)
      }
      break
    default:
      console.error('图层类型异常')
      break
  }
}

/**
 * 数据处理，接口请求数据 => 成果数据
 * 根据不同类型数据，通过子方法处理成对应的成果数据
 * @param {Object:layerGroupData} data 接口请求的图层组详情数据
 * @returns 处理完成后的标准成果数据，详细格式查看对应md
 */
function dataProcessing (data) {
  // 获取类型别名
  const { MVT, MODEL, BUILDING, TERMINAL, GRID, IMAGE, TERRAIN } =
    dmap.LayerType
  const resultData = {}
  const layer = data.geoLayerCategoryReqMaps
  // 处理矢量切片
  if (layer[IMAGE]) {
    const layerImage = dataProcessingImage(layer[IMAGE])
    if (layerImage) resultData[IMAGE] = layerImage
  }
  // 处理矢量切片
  if (layer[MVT]) {
    const layerMvt = dataProcessingMvt(layer[MVT])
    if (layerMvt) resultData[MVT] = layerMvt
  }
  // 处理矢量切片
  if (layer[TERRAIN]) {
    const layerTerrain = dataProcessingTerrain(layer[TERRAIN])
    if (layerTerrain) resultData[TERRAIN] = layerTerrain
  }
  // 处理三维模型
  if (layer[MODEL]) {
    const layerModel = dataProcessingModel(layer[MODEL])
    if (layerModel) resultData[MODEL] = layerModel
  }
  // 处理三维切片
  if (layer[BUILDING]) {
    const layerBuilding = dataProcessingBuilding(layer[BUILDING])
    if (layerBuilding) resultData[BUILDING] = layerBuilding
  }
  resultData[TERMINAL] = {}
  resultData[GRID] = {}
  return resultData
}
/**
 * 数据处理影像切片
 * @param {Object} data 接口请求的图层组影像切片数据
 * @returns {Object} 处理完成后的标准成果数据，获取失败返回null
 */
function dataProcessingImage (data) {
  if (data && data.geoLayerConfigs) {
    const geoLayerConfigsNew = data.geoLayerConfigs.map((item) => {
      serverRangeList.value.push(getQueryVariable(item.url, 'range'))
      return {
        ...item,
        url: item.url.indexOf('?') > -1 ? item.url.split('?')[0] : item.url
      }
    })
    const { geoLayerConfigs, ...rest } = data
    return {
      ...rest,
      geoLayerConfigs: geoLayerConfigsNew
    }
  }
  return null
}
/**
 * 数据处理地形切片
 * @param {Object} data 接口请求的图层组影像地形数据
 * @returns {Object} 处理完成后的标准成果数据，获取失败返回null
 */
function dataProcessingTerrain (data) {
  if (data && data.geoLayerConfigs) {
    const geoLayerConfigsNew = data.geoLayerConfigs.map((item) => {
      serverRangeList.value.push(getQueryVariable(item.url, 'range'))
      return {
        ...item,
        url: item.url.indexOf('?') > -1 ? item.url.split('?')[0] : item.url
      }
    })
    const { geoLayerConfigs, ...rest } = data
    return {
      ...rest,
      geoLayerConfigs: geoLayerConfigsNew
    }
  }
  return null
}
/**
 * 数据处理矢量切片MVT
 * @param {Object} data 接口请求的图层组矢量切片数据
 * @returns {Object} 处理完成后的标准成果数据，获取失败返回null
 */
function dataProcessingMvt (data) {
  if (data && data.geoLayerConfigs) {
    const geoLayerConfigsNew = data.geoLayerConfigs.map((item) => {
      const layerName = getLayerName(item.url)
      serverRangeList.value.push(getQueryVariable(item.url, 'range'))
      return {
        ...item,
        options: {
          layerName,
          url: item.url.indexOf('?') > -1 ? item.url.split('?')[0] : item.url,
          style: MapStyle[dmap.LayerType.MVT][layerName] || {}
        }
      }
    })
    const { geoLayerConfigs, ...rest } = data
    return {
      ...rest,
      geoLayerConfigs: geoLayerConfigsNew
    }
  }
  return null
}
/**
 * 数据处理三维模型model
 * @param {Object} data 接口请求的图层组三维模型数据
 * @returns {Object}处理完成后的标准成果数据，获取失败返回null
 */
function dataProcessingModel (data) {
  if (data && data.geoLayerConfigs) {
    const geoLayerConfigsNew = data.geoLayerConfigs.map((item) => {
      const resource = getQueryVariable(item.url, 'url')
      serverRangeList.value.push(getQueryVariable(item.url, 'range'))
      return {
        ...item,
        options: {
          resource,
          visualVariables: { field: 'object_a_2', deviation: 180 }
        }
      }
    })
    const { geoLayerConfigs, ...rest } = data
    return {
      ...rest,
      geoLayerConfigs: geoLayerConfigsNew
    }
  }
  return null
}
/**
 * 数据处理三维切片Building
 * @param {Object} data 接口请求的图层组三维切片数据
 * @returns {Object}处理完成后的标准成果数据，获取失败返回null
 */
function dataProcessingBuilding (data) {
  if (data && data.geoLayerConfigs) {
    const geoLayerConfigsNew = data.geoLayerConfigs.map((item) => {
      const buildingName = getBuildingName(item.url)
      const height = getQueryVariable(item.url, 'height')
      serverRangeList.value.push(getQueryVariable(item.url, 'range'))
      const result = {
        ...item,
        height
      }
      if (MapStyle[dmap.LayerType.BUILDING][buildingName]) {
        result.options = {
          renderer: MapStyle[dmap.LayerType.BUILDING][buildingName]
        }
      }
      return result
    })
    const { geoLayerConfigs, ...rest } = data
    return {
      ...rest,
      geoLayerConfigs: geoLayerConfigsNew
    }
  }
  return null
}
/**
 * 移除图层组
 */
function removeLayerGroup () {
  window.viewer.layerCollection.removeGroupById(curruntGroupId.value)
}
/**
 * 获取url中特定参数内容
 * @param {String} url url地址
 * @param {String} variable 准备获取参数的键值
 * @returns {String} 参数的值，获取失败返回空字符
 */
function getQueryVariable (url, variable) {
  let urlParams = null
  try {
    urlParams = url.split('?')[1]
  } catch (error) {
    console.error(`${url} url地址格式错误`)
  }
  let vars = []
  try {
    vars = urlParams.split('&')
  } catch (error) {
    console.info(`${url} url未带有参数`)
  }
  if (Array.isArray(vars)) {
    for (let index = 0; index < vars.length; index++) {
      const pair = vars[index].split('=')
      if (pair[0] === variable) {
        return pair[1]
      }
    }
  }
  return ''
}
/**
 * 获取3dtile地址，json之前的目录名称
 * @param {String} url tileset.json地址
 * @returns {String} 目录名称，获取失败返回空字符
 */
function getBuildingName (url) {
  const urlArr = url.split('/')
  const index = urlArr.findIndex((item) => item === 'tileset.json')
  return urlArr[index - 1] || ''
}

/**
 * 获取mvt服务对应的layerName
 * @param {String} url mvt地址
 * @returns {String} layerName
 */
function getLayerName (url) {
  const urlArr = url.split('/')
  const index = urlArr.findIndex((item) => item === 'mvt')
  return urlArr[index + 1] || ''
}

onMounted(() => {})

defineExpose({
  init
})
</script>
<style lang="less">
.viewPosition {
  width: 420px;
  height: 132px;
  right: 130px;
  position: absolute;
  top: 40px;
  background: #061631b6;
  border-radius: 0px;
  .header {
    width: 192px;
    height: 20px;
    font-size: 16px;
    font-family: "Microsoft YaHei UI";
    font-weight: 400;
    color: #ffffff;
    top: 20px;
    left: 114px;
    position: relative;
  }

  .form {
    position: relative;
    top: 58px;
    // left: 54px;
    font-size: 14px;
    font-family: "Microsoft YaHei UI";
  }

  .cancel {
    width: 150px;
    height: 34px;
    background: #f2f2f2;
    border: 0px solid #e9e9e9;
    border-radius: 0px;
    margin-right: 9px;
    color: #222222;
  }

  .confirm {
    width: 150px;
    height: 34px;
    background: #2071f5;
    border: 0px solid #e9e9e9;
    margin-left: 9px;
    color: #ffffff;
  }
}
</style>
